package com.yixin.hospital.controller;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yixin.hospital.common.ApiResult;
import com.yixin.hospital.common.Constant;
import com.yixin.hospital.entity.bo.UserDeptWorkAddressJobOffice;
import com.yixin.hospital.entity.domain.*;
import com.yixin.hospital.entity.dto.req.drugdepositoryAuth.DrugDepositoryAuthReqDTO;
import com.yixin.hospital.entity.dto.req.patient.PatientAddReqDTO;
import com.yixin.hospital.entity.vo.DrugDepositoryAuthVo;
import com.yixin.hospital.entity.vo.JobDutyVO;
import com.yixin.hospital.enums.DrugDepositoryOtpTypeEnum;
import com.yixin.hospital.enums.ResponseCodeEnum;
import com.yixin.hospital.service.*;
import com.yixin.hospital.utils.CaffeineUtils;
import com.yixin.hospital.utils.JwtUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import static com.yixin.hospital.common.Constant.USER_CACHE;

@RestController
@RequestMapping("/drug-depository-auth")
@Api(value = "药品仓库权限管理", tags = "药品仓库权限管理")
@Slf4j
public class DrugDepositoryAuthController {

    @Resource
    DrugDepositoryService drugDepositoryService;
    @Resource
    DrugDepositoryDutyAuthService drugDepositoryDutyAuthService;
    @Resource
    DrugDepositoryUserAuthService drugDepositoryUserAuthService;
    @Resource
    JobDutyService jobDutyService;
    @Resource
    DeptService deptService;
    @Resource
    UserService userService;

    @GetMapping("/list")
    @ApiOperation(value = "药品仓库权限列表")
    public ApiResult<?> list(HttpServletRequest request) {
        Long userId = JwtUtil.getUserId(request.getHeader(Constant.AUTHORIZATION));
        List<DrugDepository> drugDepositoryList = drugDepositoryService.list();
        List<DrugDepositoryAuthVo> resList = new ArrayList<>();
        for (DrugDepository drugDepository : drugDepositoryList) {
            // drugDepository
            DrugDepositoryAuthVo drugDepositoryAuthVo = new DrugDepositoryAuthVo();
            drugDepositoryAuthVo.setDrugDepositoryId(drugDepository.getId());
            drugDepositoryAuthVo.setDrugDepositoryName(drugDepository.getName());
            // optTypeInfo
            this.getOptTypeInfoList(drugDepository, drugDepositoryAuthVo);
            resList.add(drugDepositoryAuthVo);
        }
        return ApiResult.success(resList);
    }

    /**
     * 查看库的 各权限所有的部门-职务
     *
     * @param drugDepository
     * @param drugDepositoryAuthVo
     * @return
     */
    private void getOptTypeInfoList(DrugDepository drugDepository, DrugDepositoryAuthVo drugDepositoryAuthVo) {
        // 各权限
        for (DrugDepositoryOtpTypeEnum value : DrugDepositoryOtpTypeEnum.values()) {
            int optType = value.getCode();
            List<DrugDepositoryDutyAuth> jobDutyList = drugDepositoryDutyAuthService.list(new LambdaQueryWrapper<DrugDepositoryDutyAuth>().eq(DrugDepositoryDutyAuth::getDrugDepositoryId, drugDepository.getId()).eq(DrugDepositoryDutyAuth::getOptType, optType));
            List<JobDutyVO> jobDutyVOList = new ArrayList<>();
            // 允许的部门
            for (DrugDepositoryDutyAuth drugDepositoryDutyAuth : jobDutyList) {
                JobDutyVO jobDutyVO = new JobDutyVO();
                JobDuty jobDuty = jobDutyService.getById(drugDepositoryDutyAuth.getJobDutyId());
                jobDutyVO.setDeptId(jobDuty.getDeptId());
                Dept dept = deptService.getById(jobDuty.getDeptId());
                jobDutyVO.setDeptName(dept.getName());
                jobDutyVO.setId(jobDuty.getId());
                jobDutyVO.setName(jobDuty.getName());
                long count = userService.count(new LambdaQueryWrapper<User>().like(User::getJobDuty, jobDuty.getId()));
                jobDutyVO.setCountUserByJobDuty(count);
                long count1 = drugDepositoryUserAuthService.count(new LambdaQueryWrapper<DrugDepositoryUserAuth>().eq(DrugDepositoryUserAuth::getDrugDepositoryId, drugDepository.getId()).eq(DrugDepositoryUserAuth::getOptType, optType));
                jobDutyVO.setCountUserByAuth(count1);
                jobDutyVOList.add(jobDutyVO);
            }
            if (optType == DrugDepositoryOtpTypeEnum.QUERY.getCode()) {
                drugDepositoryAuthVo.setQueryInfo(jobDutyVOList);
            } else if (optType == DrugDepositoryOtpTypeEnum.SELL.getCode()) {
                drugDepositoryAuthVo.setSellInfo(jobDutyVOList);
            } else if (optType == DrugDepositoryOtpTypeEnum.INPUT.getCode()) {
                drugDepositoryAuthVo.setInputInfo(jobDutyVOList);
            } else if (optType == DrugDepositoryOtpTypeEnum.OUTPUT.getCode()) {
                drugDepositoryAuthVo.setOutputInfo(jobDutyVOList);
            } else if (optType == DrugDepositoryOtpTypeEnum.CHECK.getCode()) {
                drugDepositoryAuthVo.setCheckInfo(jobDutyVOList);
            } else if (optType == DrugDepositoryOtpTypeEnum.WRITE_OFF.getCode()) {
                drugDepositoryAuthVo.setWriteOffInfo(jobDutyVOList);
            } else if (optType == DrugDepositoryOtpTypeEnum.PURCHASE.getCode()) {
                drugDepositoryAuthVo.setPurchaseInfo(jobDutyVOList);
            } else if (optType == DrugDepositoryOtpTypeEnum.COST_PRICE.getCode()) {
                drugDepositoryAuthVo.setCostPriceInfo(jobDutyVOList);
            }
        }
    }

    @PostMapping("/add")
    @ApiOperation(value = "添加权限")
    public ApiResult add(@Valid @RequestBody DrugDepositoryAuthReqDTO reqDTO, HttpServletRequest request) {
        String userName = JwtUtil.getName(request.getHeader(Constant.AUTHORIZATION));
        List<DrugDepositoryDutyAuth> list = drugDepositoryDutyAuthService.list(new LambdaQueryWrapper<DrugDepositoryDutyAuth>()
                .eq(DrugDepositoryDutyAuth::getDrugDepositoryId, reqDTO.getDrugDepositoryId())
                .eq(DrugDepositoryDutyAuth::getJobDutyId, reqDTO.getJobDutyId())
                .eq(DrugDepositoryDutyAuth::getOptType, reqDTO.getOptType()));
        if (list.size() != 0) return ApiResult.error(ResponseCodeEnum.AUTH_EXIST.getCode(), ResponseCodeEnum.AUTH_EXIST.getMsg());
        DrugDepositoryDutyAuth drugDepositoryDutyAuth = new DrugDepositoryDutyAuth();
        drugDepositoryDutyAuth.setDrugDepositoryId(reqDTO.getDrugDepositoryId());
        drugDepositoryDutyAuth.setJobDutyId(reqDTO.getJobDutyId());
        drugDepositoryDutyAuth.setOptType(reqDTO.getOptType());
        drugDepositoryDutyAuth.setCreatedBy(userName);
        drugDepositoryDutyAuthService.save(drugDepositoryDutyAuth);
        // user auth
        List<User> userList = userService.list(new LambdaQueryWrapper<User>().like(User::getJobDuty, reqDTO.getJobDutyId()));
        for (User user : userList) {
            long count = drugDepositoryUserAuthService.count(new LambdaQueryWrapper<DrugDepositoryUserAuth>()
                    .eq(DrugDepositoryUserAuth::getDrugDepositoryId, reqDTO.getDrugDepositoryId())
                    .eq(DrugDepositoryUserAuth::getUserId, user.getId())
                    .eq(DrugDepositoryUserAuth::getOptType, reqDTO.getOptType()));
            if (count!=0) continue;
            DrugDepositoryUserAuth drugDepositoryUserAuth = new DrugDepositoryUserAuth();
            drugDepositoryUserAuth.setDrugDepositoryId(reqDTO.getDrugDepositoryId());
            drugDepositoryUserAuth.setUserId(user.getId());
            drugDepositoryUserAuth.setOptType(reqDTO.getOptType());
            drugDepositoryUserAuth.setCreatedBy(userName);
            drugDepositoryUserAuthService.save(drugDepositoryUserAuth);
        }
        return ApiResult.success();
    }

    @DeleteMapping("/remove")
    @ApiOperation(value = "删除权限")
    public ApiResult remove(@Valid @RequestBody DrugDepositoryAuthReqDTO reqDTO) {
        LambdaQueryWrapper<DrugDepositoryDutyAuth> queryWrapper = new LambdaQueryWrapper<DrugDepositoryDutyAuth>()
                .eq(DrugDepositoryDutyAuth::getDrugDepositoryId, reqDTO.getDrugDepositoryId())
                .eq(DrugDepositoryDutyAuth::getJobDutyId, reqDTO.getJobDutyId())
                .eq(DrugDepositoryDutyAuth::getOptType, reqDTO.getOptType());
        drugDepositoryDutyAuthService.remove(queryWrapper);
        // 删除拥有该职务的用户权限
        List<User> userList = userService.list(new LambdaQueryWrapper<User>().like(User::getJobDuty, reqDTO.getJobDutyId()));
        if (!CollectionUtils.isEmpty(userList)) {
            List<Long> ids = userList.stream().map(User::getId).collect(Collectors.toList());
            drugDepositoryUserAuthService.remove(new LambdaQueryWrapper<DrugDepositoryUserAuth>()
                    .eq(DrugDepositoryUserAuth::getDrugDepositoryId, reqDTO.getDrugDepositoryId())
                    .eq(DrugDepositoryUserAuth::getOptType, reqDTO.getOptType())
                    .in(DrugDepositoryUserAuth::getUserId, ids));
        }
        return ApiResult.success();
    }

    /**
     * 校验库权限
     * @param userId
     * @param depositoryId
     * @param optType
     * @return
     */
    public boolean checkDrugDepositoryAuth(Long userId, Long depositoryId, Integer optType) {
        List<DrugDepositoryUserAuth> userAuthList = drugDepositoryUserAuthService.list(new LambdaQueryWrapper<DrugDepositoryUserAuth>()
                .eq(DrugDepositoryUserAuth::getUserId, userId)
                .eq(DrugDepositoryUserAuth::getDrugDepositoryId, depositoryId)
                .eq(DrugDepositoryUserAuth::getOptType, optType));
        if (CollectionUtils.isEmpty(userAuthList)) return false;
        // 获取当前用户登录职务 有该操作权限
        List<UserDeptWorkAddressJobOffice> loginList = (List<UserDeptWorkAddressJobOffice>) CaffeineUtils.get(USER_CACHE);
        UserDeptWorkAddressJobOffice loginUser = loginList.stream().filter(u -> u.getUserId().equals(userId)).collect(Collectors.toList()).get(0);
        Long jobDutyId = loginUser.getJobDutyId();
        List<DrugDepositoryDutyAuth> JobDutyAuthList = drugDepositoryDutyAuthService.list(new LambdaQueryWrapper<DrugDepositoryDutyAuth>()
                .eq(DrugDepositoryDutyAuth::getJobDutyId, jobDutyId)
                .eq(DrugDepositoryDutyAuth::getDrugDepositoryId, depositoryId)
                .eq(DrugDepositoryDutyAuth::getOptType, optType));
        if (CollectionUtils.isEmpty(JobDutyAuthList)) return false;
        return true;
    }

    /**
     * 根据权限查询库
     * @param optType
     * @return
     */
    @GetMapping("/query-depositoryIds-by-optType")
    @ApiOperation(value = "根据操作权限查库列表")
    public ApiResult<List<Long>> getDepositoryIdListByAuth(@RequestParam Integer optType, HttpServletRequest request) {
        Long userId = JwtUtil.getUserId(request.getHeader(Constant.AUTHORIZATION));
        List<Long> drugDepositoryIdList = new ArrayList<>();
        List<DrugDepositoryUserAuth> userAuthList = drugDepositoryUserAuthService.list(new LambdaQueryWrapper<DrugDepositoryUserAuth>()
                .eq(DrugDepositoryUserAuth::getUserId, userId)
                .eq(DrugDepositoryUserAuth::getOptType, optType));
        log.info("userAuthList: {}", userAuthList);
        if (CollectionUtils.isEmpty(userAuthList)) return ApiResult.success(drugDepositoryIdList);
        // 获取当前用户登录职务 有该操作权限
        List<UserDeptWorkAddressJobOffice> loginList = (List<UserDeptWorkAddressJobOffice>) CaffeineUtils.get(USER_CACHE);
        UserDeptWorkAddressJobOffice loginUser = loginList.stream().filter(u -> u.getUserId().equals(userId)).collect(Collectors.toList()).get(0);
        Long jobDutyId = loginUser.getJobDutyId();
        List<DrugDepositoryDutyAuth> JobDutyAuthList = drugDepositoryDutyAuthService.list(new LambdaQueryWrapper<DrugDepositoryDutyAuth>()
                .eq(DrugDepositoryDutyAuth::getJobDutyId, jobDutyId)
                .eq(DrugDepositoryDutyAuth::getOptType, optType));
        log.info("JobDutyAuthList: {}", JobDutyAuthList);
        if (CollectionUtils.isEmpty(JobDutyAuthList)) return ApiResult.success(drugDepositoryIdList);
        log.info("drugDepositoryIdList: {}", drugDepositoryIdList);
        drugDepositoryIdList = userAuthList.stream().map(DrugDepositoryUserAuth::getDrugDepositoryId).collect(Collectors.toList());
        return ApiResult.success(drugDepositoryIdList);
    }

}
